#-*- coding: utf-8 -*-
'''
@Authors: Miguel Rodrigues, 5959;
          Ricardo Nunes, 5623
@Date: 29 Novembro 2012
@Obs: main
'''

import numpy as np
import matplotlib.pyplot as plt
import sqlite3
import xlrd
import csv


class CoreLibrary():
    #Criação da Base De Dados
    def create_database(self,db):
        '''
        Cria a base de dados e respectiva tabela
        '''
        conn = sqlite3.connect(db)
        c = conn.cursor()
        c.execute('''create table if not exists tabela (INDICE interger, CURSO text,
            FORMACAO text, ESCOLA text, INSTITUTO text, ANO text, M_INSCRITOS text, F_INSCRITOS text, T_INSCRITOS text)''')
        conn.commit()
        conn.close()
        pass

    # Insere os dados na Base de Dados
    def fill_up_database(self, db, xls_file):
        '''
        Abre a folha de calculo "Tabela 4.1" do ficheiro Inscritos_2010-2011.xls"
        '''
        excelfile = xlrd.open_workbook(xls_file)
        reader = excelfile.sheet_by_name('Tabela 4.1')

        '''
        Carrega a base de dados
        '''
        conn = sqlite3.connect(db)
        cursor = conn.cursor()

        #Transfere os registos da "Tabela 4.1" para a base de dados:
        position=0
        arrayInput = range(0, 9)

        '''
        Processa toda a tabela, linha por linha
        '''
        for row_i in range(reader.nrows):
            '''
            Filtra os dados, aceitando somente os registos com as palavras "COMPUTADORES" e "INFORMÁTICA" no campo "Curso Superior"
            '''
            if (("COMPUTADORES".decode('utf-8') in reader.row_values(row_i)[3].upper()) or "INFORMÁTICA".decode('utf-8')
                in reader.row_values(row_i)[3].upper()):
                '''
                Repete os dados três vezes por ano lectivo, contantando com o seu genéro, masculino e feminino, e o seu total. 
                '''
                for i in range(5, 51, 3):
                    #Lê as linhas, coluna por coluna
                    position=position+1
                    '''
                    Adiciona o Indice
                    '''
                    arrayInput[0] = position # INDICE

                    '''
                    Adiciona o Curso
                    '''
                    arrayInput[1] = reader.row_values(row_i)[3].encode('utf-8') # CURSO

                    '''
                    Adiciona o nível de formação de acordo com a última linha com registos. (salta vazias)
                    '''
                    temprow = row_i
                    while len(reader.row_values(temprow)[2])==0:
                        temprow=temprow-1
                        pass
                    arrayInput[2] = reader.row_values(temprow)[2].encode('utf-8') # FORMACAO

                    '''
                    Adiciona a unidade orgânica de acordo com a última linha com registos. (salta vazias)
                    '''
                    while len(reader.row_values(temprow)[1])==0:
                        temprow=temprow-1
                        pass           
                    arrayInput[3] = reader.row_values(temprow)[1].encode('utf-8') # ESCOLA

                    '''
                    Adiciona o estabelecimento de ensino de acordo com a última linha com registos. (salta vazias)
                    '''
                    while len(reader.row_values(temprow)[0])==0:
                        temprow=temprow-1
                        pass
                    arrayInput[4] = reader.row_values(temprow)[0].encode('utf-8') # INSTITUTO

                    '''
                    Adiciona o Ano Lectivo
                    '''
                    #Se a coluna estiver vazia então salta-a
                    if len(reader.row_values(2)[i])==0:
                            i+=1
                    #Obtém somente o ano lectivo, excluindo referências na tabela, por exemplo " (3)".
                    arrayInput[5] = reader.row_values(2)[i].encode('utf-8').rsplit(' ', 1)[0] # ANO

                    '''
                    Processa a contagem dos géneros
                    '''
                    for y in range(0, 2):
                        '''
                        Adiciona a contagem de género masculino
                        '''
                        # Substitui "-" (campo vazio) por "0"
                        if reader.row_values(row_i)[i]== "-":
                            arrayInput[6]="0"
                        else:
                            arrayInput[6] = reader.row_values(row_i)[i] # MASCULINO
                            pass
                        '''
                        Adiciona a contagem de género feminino
                        '''
                        if reader.row_values(row_i)[i]== "-":
                            arrayInput[7]="0"
                        else:
                            arrayInput[7] = reader.row_values(row_i)[i+1] # FEMININO
                            pass

                        '''
                        Adiciona a contagem total de géneros
                        '''
                        if reader.row_values(row_i)[i]== "-":
                            arrayInput[8]="0"
                        else:
                            arrayInput[8] = reader.row_values(row_i)[i+2] # TOTAL
                            pass
                        pass

                    '''
                    Gera e executa o Script em SQL para inserir o registo na base de dados
                    '''
                    cursor.execute('''insert into tabela (INDICE, CURSO, FORMACAO, ESCOLA, INSTITUTO, ANO, M_INSCRITOS, F_INSCRITOS, T_INSCRITOS)
                                values ("{0}", "{1}", "{2}", "{3}", "{4}", "{5}", "{6}",  "{7}",  "{8}")'''.format(str(arrayInput[0]),
                                        str(arrayInput[1]), str(arrayInput[2]), str(arrayInput[3]), str(arrayInput[4]),
                                        str(arrayInput[5]), str(arrayInput[6]), str(arrayInput[7]), str(arrayInput[8])))            
                    pass                
                    
                pass

        '''
        Processa o conjunto de procedimentos/scripts na base de dados e fecha a conexão.
        '''
        conn.commit()    
        conn.close()
        pass

    '''
    Estatistica de cursos em associação com o estabelecimento de ensino,
    unidade orgânica e anos letivos em que funcionaram
    @param db            O nome da base de dados
    @return              Devolve uma tabela com a seguinte estrutura: "Curso", "Escola", "Instituto", "Total de Inscritos"
    '''
    def statistic1(self, db):
        outputData = list()
        for i in range(1995, 2011): 
            year = "{0}/{1}".format(i, str(i + 1)[2:])
            conn = sqlite3.connect(db)
            c = conn.cursor()
            c.execute("SELECT CURSO, ESCOLA, INSTITUTO, T_INSCRITOS FROM 'tabela' WHERE ANO='{0}' AND T_INSCRITOS<>'0'".decode("utf-8").format(year).encode("utf-8"))
            stat_value = c.fetchall()
            conn.close()
            outputData.extend(stat_value)
        return outputData

    '''
    Estatistica discriminando a quantidade de alunos se inscreveram ao longo dos anos;
    @param db            O nome da base de dados
    @return              Devolve uma tabela com a seguinte estrutura: "Total de Inscritos", "Ano Lectivo"
    '''
    def statistic2(self, db):
        outputData = list()
        for i in range(1995, 2011):
            year = "{0}/{1}".format(i, str(i + 1)[2:])
            conn = sqlite3.connect(db)
            c = conn.cursor()
            c.execute("SELECT T_INSCRITOS, ANO FROM 'tabela' WHERE ANO='{0}'".decode("utf-8").format(year).encode("utf-8"))
            stat_value = c.fetchall()
            conn.close()
            soma = 0
            for i in range(0, len(stat_value)):
                soma = soma + int(round(float(stat_value[i][0])))
            outputData.append([str(soma), year])
        return outputData
        
    '''
    Estatistica discriminado a quantidade de cursos por nível de formação ao longo dos anos;
    @param db            O nome da base de dados
    @return              Devolve uma tabela com a seguinte estrutura: "Ano", "Nível de Formação", "Total de Inscritos"
    '''
    def statistic3(self, db):
        outputData = list()
        for i in range(1995, 2011):
            year = "{0}/{1}".format(i, str(i + 1)[2:])
            conn = sqlite3.connect(db)
            c = conn.cursor()
            c.execute("SELECT COUNT(CURSO), FORMACAO FROM 'tabela' WHERE ANO='{0}' AND T_INSCRITOS<>'0' GROUP BY FORMACAO".decode("utf-8").format(year).encode("utf-8"))
            stat_value = c.fetchall()
            conn.close()
            for i in range(0, len(stat_value)):
                outputData.append([str(year), stat_value[i][1], str(int(round(float(stat_value[i][0]))))])
        return outputData
        
    '''
    Estatistica discriminado a quantidade de alunos por nível de formação ao longo dos anos.
    @param db            O nome da base de dados
    @return              Devolve uma tabela com a seguinte estrutura: "Ano", "Total de Inscritos", "Nível de Formação"
    '''
    def statistic4(self, db):
        outputData = list()        
        for i in range(1995, 2011):
            year = "{0}/{1}".format(i, str(i + 1)[2:])
            conn = sqlite3.connect(db)
            c = conn.cursor()
            c.execute("SELECT T_INSCRITOS, FORMACAO FROM 'tabela' WHERE ANO='{0}' AND T_INSCRITOS<>'0' ORDER BY FORMACAO".decode("utf-8").format(year).encode("utf-8"))
            stat_value = c.fetchall()
            conn.close()
            soma = 0.0
            for i in range(0, len(stat_value)):
                soma = soma + float(stat_value[i][0])
                if i != len(stat_value)-1:
                    if stat_value[i][1] <> stat_value[i+1][1]:
                        outputData.append([year, str(int(round(float(soma)))), stat_value[i][1]])
                        soma = 0.0
                        pass
                else:
                    outputData.append([year, str(int(round(float(soma)))), stat_value[i][1]])
                    soma = 0.0
        return outputData                    
        pass

    '''
    Exporta um consjunto de dados tabulados para um ficheiro de valores
    separados por virgula (CSV Comma Separated Values File)
    @param outputFile    Localização do ficheiro a exportar
    @param headers       Cabeçalho da tabela
    @param data          tabela com os valores
    '''
    def send_to_csv(self, outputFile, headers, data):
        outputFile = open(outputFile, 'wb')
        csvWriter = csv.writer(outputFile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
        csvWriter.writerow(headers)
        for row in data:
            csvWriter.writerow([unicode(col).encode("utf-8") for col in row])
        outputFile.close()
        pass

    '''
    Desenha os gráficos de acordo com os dados obtidos.
    @param data     Tabela com os dados a descriminar
                    (primeira Coluna, eixo dos XX)
                    (segunda Coluna, eixo dos YY)
    @param title    Titulo do gráfico
    @param legend   Legenda do gráfico
    @param color    Cor das barras
    '''
    def plot_statistics(self, data, title="Untitled", legend=["No Legend"], color='b'):
        #Não Testado!!!
        N = len(data)
        ind = np.arange(N)
        width = 0.35

        p1 = plt.bar(ind, [int(row[0]) for row in data], width)
 
        plt.title(title)
        plt.xticks(ind+width/2., [row[1] for row in data])
        
        plt.yticks(np.arange(0, max([int(row[0]) for row in data]) + 1, max([int(row[0]) for row in data]) / 10.0))
        plt.show()
        pass
